

package org.finesys.system.controller;

import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.finesys.common.constants.BaseConstant;
import org.finesys.common.core.constants.RestApiConfig;
import org.finesys.common.core.exception.ErrorCodes;
import org.finesys.common.core.module.R;
import org.finesys.common.core.util.MessageUtil;
import org.finesys.common.excel.annotaion.RequestExcel;
import org.finesys.common.excel.annotaion.ResponseExcel;
import org.finesys.common.log.core.annotation.LogAnnotation;
import org.finesys.common.log.core.enums.OperateType;
import org.finesys.common.security.core.annotation.Inner;
import org.finesys.common.security.core.module.AuthUser;
import org.finesys.common.security.core.util.SecurityUtils;
import org.finesys.common.tenant.aspect.IgnoreTenant;
import org.finesys.system.api.dto.SysUserDTO;
import org.finesys.system.api.dto.UserInfo;
import org.finesys.system.api.entity.SysUser;
import org.finesys.system.api.vo.UserExcelVO;
import org.finesys.system.api.vo.UserVO;
import org.finesys.system.constants.ControllerRestApiConfig;
import org.finesys.system.service.SysUserService;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;


@RestController
@RequiredArgsConstructor
@RequestMapping(ControllerRestApiConfig.USER)
@Tag(name = "用户管理模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysUserController {

    private final SysUserService userService;

    /**
     * 获取当前用户全部信息
     *
     * @return 用户信息
     */
    @Operation(summary = "获取当前用户全部信息")
    @GetMapping(value = {"/info"})
    public R<UserInfo> info() {
        AuthUser authUser = SecurityUtils.getUser();
        SysUser user = userService.getById(authUser.getUserId());
        UserInfo userInfo = userService.getUserInfo(user);
        return R.success(userInfo);
    }

    /**
     * 获取指定用户全部信息
     *
     * @return 用户信息
     */
    @Inner
    @GetMapping(value = {"/info/query"})
    public R<?> info(@RequestParam(required = false) String username, @RequestParam(required = false) String phone) {
        SysUser user = userService.getOne(Wrappers.<SysUser>query()
                .lambda()
                .eq(StrUtil.isNotBlank(username), SysUser::getUsername, username)
                .eq(StrUtil.isNotBlank(phone), SysUser::getPhone, phone));
        if (user == null) {
            return R.failed(MessageUtil.getMessage(ErrorCodes.SYS_USER_USERINFO_EMPTY, username));
        }
        return R.success(userService.getUserInfo(user));
    }

    /**
     * 获取指定用户全部信息
     *
     * @return 用户信息
     */
    @Operation(summary = "通过用户名查找用户信息")
    @Inner
    @IgnoreTenant
    @GetMapping("/findByName/{username}")
    public R<UserInfo> findByName(@PathVariable String username) {
        SysUser user = userService.findByName(username);
        return R.success(userService.getUserInfo(user));
    }

    /**
     * 通过用户手机号查找用户信息
     *
     * @param mobile 手机号
     * @return 用户信息
     */
    @Operation(summary = "通过用户手机号查找用户信息")
    @Inner
    @IgnoreTenant
    @GetMapping("/findByMobile/{mobile}")
    public R<UserInfo> findByMobile(@PathVariable String mobile) {
        SysUser user = userService.findByMobile(mobile);
        return R.success(userService.getUserInfo(user));
    }

    /**
     * 通过员工号查找用户信息
     *
     * @param userSN 员工号
     * @return 用户信息
     */
    @Operation(summary = "通过用户手机号查找用户信息")
    @Inner
    @IgnoreTenant
    @GetMapping("/user/findByUserSN/{userSN}")
    public R<UserInfo> findByUserSN(@PathVariable String userSN) {
        SysUser user = userService.findByUserSN(userSN);
        return R.success(userService.getUserInfo(user));
    }

    /**
     * 通过ID查询用户信息
     *
     * @param id ID
     * @return 用户信息
     */
    @GetMapping("/{id:\\d+}")
    public R<UserVO> user(@PathVariable Long id) {
        return R.success(userService.selectUserVoById(id));
    }

    /**
     * 查询用户信息
     *
     * @param query 查询条件
     * @return 不为空返回用户名
     */
    @Inner(value = false)
    @GetMapping(RestApiConfig.DETAILS)
    public R<?> getDetails(@ParameterObject SysUser query) {
        SysUser sysUser = userService.getOne(Wrappers.query(query), false);
        return R.success(sysUser == null ? null : BaseConstant.NORMAL);
    }

    /**
     * 删除用户信息
     *
     * @param id ID
     * @return R
     */
    @LogAnnotation(title = "删除用户信息", operateType = OperateType.DELETE)
    @DeleteMapping("/{id:\\d+}")
    @PreAuthorize("@pms.hasPermission('sys_user_del')")
    public R<Boolean> userDel(@PathVariable Long id) {
        SysUser sysUser = userService.getById(id);
        return R.success(userService.removeUserById(sysUser));
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds ID
     * @return R
     */
    @LogAnnotation(title = "删除用户信息", operateType = OperateType.DELETE)
    @DeleteMapping(RestApiConfig.DELETE)
    @PreAuthorize("@pms.hasPermission('sys_user_del')")
    public R<Boolean> delete(@RequestBody Long[] userIds) {
        return R.success(userService.removeUsers(userIds));
    }

    /**
     * 添加用户
     *
     * @param userDto 用户信息
     * @return success/false
     */
    @LogAnnotation(title = "添加用户", operateType = OperateType.INSERT)
    @PostMapping(value = RestApiConfig.ADD)
    @PreAuthorize("@pms.hasPermission('sys_user_add')")
    public R<Boolean> user(@RequestBody SysUserDTO userDto) {
        return R.success(userService.saveUser(userDto));
    }

    /**
     * 管理员更新用户信息
     *
     * @param userDto 用户信息
     * @return R
     */
    @LogAnnotation(title = "更新用户信息", operateType = OperateType.UPDATE)
    @PutMapping(value = RestApiConfig.UPDATE)
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    public R<Boolean> update(@Valid @RequestBody SysUserDTO userDto) {
        return R.success(userService.updateUser(userDto));
    }

    /**
     * 分页查询用户
     *
     * @param page    参数集
     * @param userDTO 查询参数列表
     * @return 用户集合
     */
    @GetMapping(value = RestApiConfig.PAGE)
    public R<IPage<UserVO>> getUserPage(Page<SysUserDTO> page, SysUserDTO userDTO) {
        return R.success(userService.getUserVOPage(page, userDTO));
    }

    /**
     * 个人修改个人信息
     *
     * @param userDto userDto
     * @return success/false
     */
    @LogAnnotation(title = "修改个人信息", operateType = OperateType.UPDATE)
    @PutMapping("/edit")
    public R<Boolean> edit(@Valid @RequestBody SysUserDTO userDto) {
        userDto.setUsername(SecurityUtils.getUser().getUsername());
        return R.success(userService.updateUserInfo(userDto));
    }

    @PutMapping("/password")
    public R<?> password(@RequestBody SysUserDTO userDto) {
        String username = SecurityUtils.getUser().getUsername();
        userDto.setUsername(username);
        return userService.changePassword(userDto);
    }

    @PostMapping("/check")
    public R<?> check(String password) {
        return userService.checkPassword(password);
    }

    /**
     * 管理员更新用户信息
     *
     * @param userDto 用户信息
     * @return R
     */
    @LogAnnotation(title = "更新用户状态信息", operateType = OperateType.UPDATE)
    @PutMapping(value = RestApiConfig.CHANGE_STATUS)
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    public R<?> changeStatus(@Valid @RequestBody SysUserDTO userDto) {
        return userService.changeStatus(userDto);
    }

    /**
     * 获取展示列信息
     */
    @GetMapping(RestApiConfig.COLUMNS)
    public R<List<Map<String, Object>>> getColumns() {
        SysUser sysUser = new SysUser();
        List<Map<String, Object>> userColumns = sysUser.getColumns();
        return R.success(userColumns);
    }

    /**
     * 导入
     */
    @PostMapping(RestApiConfig.IMPORT_EXCEL)
    @PreAuthorize("@pms.hasPermission('sys_user_import')")
    public R<?> importExcel(@RequestExcel List<UserExcelVO> userExcelVOList, BindingResult bindingResult) {
        return userService.importUser(userExcelVOList, bindingResult);
    }

    /**
     * 导出
     */
    @ResponseExcel
    @GetMapping(RestApiConfig.EXPORT_EXCEL)
    @PreAuthorize("@pms.hasPermission('sys_user_export')")
    public List<UserExcelVO> exportExcel(SysUserDTO sysUserDTO) {
        return userService.listUser(sysUserDTO);
    }
}
